package view;

import game.ChessGame;
import game.MoveExecutionList;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.border.TitledBorder;

import parser.ChessMoveParser;
import parser.ImportAndExportMoveList;

import chess.Piece;
import chess.Player;

public class ChessGraphicalView extends GraphicalView {
	
	//Here are the Swing components that will be used for the graphical display
	public static final Color CURRENT_PLAYER_SELECTION_COLOR = Color.CYAN;
	public static final Color DEFAULT_PLAYER_SELECTION_COLOR = Color.WHITE;
	public static final String DEBUG_VIEW = "Debug View";
	public static final String MOVE_VIEW = "Move View";
	public static final int MAX_DEBUG_CONSOLE_LENGTH = 15000000;
	
	private JTextArea textField;
	private JTextArea moveTextField;
	private JTextArea playerOne;
	private JTextArea playerTwo;
	
	private JScrollPane playerOneScroll;
	private JScrollPane playerTwoScroll;
	//Set up an image library
	
	private JPanel sidePanel;
	private boolean debugPanelOpened;
	private JScrollPane scrollPane;
	private JScrollPane debugConsole;
	
	private JMenuItem debugOption;
	
	private ChessClockView clock;
	
	private ChessGame game;
	
	//INitializes the display
	/**
	 * The constructor for the GraphicalView class.
	 * 
	 * <pre>
	 * Caleb Chan
	 * -Creation (Feb 9, 2010)
	 * Max Joyce
	 * -Added initialization for selected x and y coordinates (Feb 12,2010)
	 * </pre>
	 */
	public ChessGraphicalView(ChessGame game){
		super(game.getBoard());
		this.game = game;
		textField = new JTextArea();
		clock = new ChessClockView(game);
		clock.enabled(true);
	}
	public void displayBoard(){
		super.displayBoard();
		if(textField != null){
			this.printlnToDebugConsole(board.toString());
		}
		if(moveTextField != null){
			moveTextField.setText(game.getMoveList());
		}
		if(playerOne != null){
			fillInPlayerGraveyard(playerOne,ChessGraphicalView.PLAYER_1);
		}
		if(playerTwo != null){
			fillInPlayerGraveyard(playerTwo,ChessGraphicalView.PLAYER_2);
		}
		
	}
	/**
	 * This will clear the debug console
	 */
	public void clearDebugConsole(){
		if(textField != null){
			textField.setText("");
		}
	}
	@Override
	public void createMenu(){
		super.createMenu();
		JMenu gameMenu = mainWindow.getJMenuBar().getMenu(1);
		JMenuItem timerOption = new JMenuItem("Timer Off");
		
		timerOption.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0){
				if(clock.isEnabled()){
					clock.enabled(!clock.isEnabled());
					JMenuItem item = (JMenuItem)arg0.getSource();
					item.setText("Timer On");
				}else{
					clock.enabled(!clock.isEnabled());
					JMenuItem item = (JMenuItem)arg0.getSource();
					item.setText("Timer Off");
				}
			}
		});
		gameMenu.add(timerOption);
	}
	/**
	 * This method will create the debug interface. This include the debug console, the move list
	 * menu option, the import menu option and the export menu option
	 * @param sidePanel The side panel to place the debug console
	 */
	private void createDebugInterface(JPanel sidePanel){
		debugPanelOpened = true;
		JMenu gameMenu = mainWindow.getJMenuBar().getMenu(1);
		JMenu helpMenu = mainWindow.getJMenuBar().getMenu(4);
		
		JMenuItem importOption = new JMenuItem("Import Moves");
		JMenuItem exportOption = new JMenuItem("Export Moves");
		
		debugOption = new JMenuItem(ChessGraphicalView.MOVE_VIEW);
		debugOption.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0){
				switchSideCenterPanel();	
			}
		});
		
		exportOption.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0){
				if(game.listOfMoves.exportList().length() != 0){
					ChessMoveParser importList = new ImportAndExportMoveList(board,game.getPlayers());
					importList.setUpSaveChooser(mainWindow);
					if(importList.writeFile()){
						showOutputMessage("File Saved");
					}else {
						showOutputMessage("File Was Not Saved");
					}
				}
			}
		});
		
		importOption.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0){
				ChessMoveParser importList = new ImportAndExportMoveList(board,game.getPlayers());
				importList.setUpLoadChooser(mainWindow);
				game.resetBoard();
				MoveExecutionList commands = importList.parseFile();
				if(commands != null){
					game.setMoveList(commands);
					game.setPlayer(importList.getCurrentPlayer());
					showOutputMessage("Import Done");
					displayBoard();
				}else{
					handleImportErrorCode(importList.getErrorCode());
				}
			}
		});
		
		gameMenu.add(importOption);
		gameMenu.add(exportOption);
		helpMenu.add(debugOption);
		createDebugPanel(sidePanel);
	}
	/**
	 * This method will create the debug panel on the side bar
	 * @param panel The side panel where the debug panel is to be creted
	 */
	private void createDebugPanel(JPanel panel){
		textField.setEditable(false);
		textField.setFont(new Font(Font.DIALOG_INPUT, Font.PLAIN, 12));
		textField.setBackground(Color.BLACK);
		textField.setForeground(Color.GREEN);
		debugConsole = new JScrollPane(textField);
		debugConsole.setPreferredSize(new Dimension(180,200));
		TitledBorder title = BorderFactory.createTitledBorder("Debug Console");
		debugConsole.setBorder(title);
		panel.add(debugConsole,BorderLayout.CENTER);
		debugOption.setText(ChessGraphicalView.MOVE_VIEW);
	}
	/**
	 * This method will create the move list on the side bar
	 * @param panel The side panel where the move list is to be created
	 */
	private void createMoveListPanel(JPanel panel){
		moveTextField = new JTextArea(game.getMoveList());
		moveTextField.setEditable(false);
		moveTextField.setFont(new Font(Font.DIALOG_INPUT, Font.PLAIN, 10));
		scrollPane = new JScrollPane(moveTextField);
		scrollPane.setPreferredSize(new Dimension(180,200));
		TitledBorder title = BorderFactory.createTitledBorder("Move List");
		moveTextField.setBorder(title);
		panel.add(scrollPane, BorderLayout.CENTER);
		if(debugOption != null){
			debugOption.setText(ChessGraphicalView.DEBUG_VIEW);
		}
	}
	/**
	 * This will create the side bar when the chess game is running. 
	 * @param showDebugMenu Places the debug panel instead of the move list panel
	 */
	public void createSideBar(boolean showDebugMenu){
		mainWindow.setSize(1100,800);
		sidePanel = new JPanel(new BorderLayout());
		sidePanel.setPreferredSize(new Dimension(300,800));
		sidePanel.setBackground(Color.CYAN);
		mainWindow.getContentPane().add(sidePanel,BorderLayout.EAST);
		
		ArrayList<Player> players = game.getPlayers(); 
		playerOne = new JTextArea(players.get(0).getName() + ":");
		playerTwo = new JTextArea(players.get(1).getName() + ":");
				
		playerOne.setFont(new Font(Font.DIALOG_INPUT, Font.PLAIN, 14));
		playerTwo.setFont(new Font(Font.DIALOG_INPUT, Font.PLAIN, 14));
		
		playerOne.setEditable(false);
		playerTwo.setEditable(false);
		// Creates the scroll for each players frame
		playerOneScroll = new JScrollPane(playerOne);
		playerOneScroll.setPreferredSize(new Dimension(180,250));
		playerTwoScroll = new JScrollPane(playerTwo);
		playerTwoScroll.setPreferredSize(new Dimension(180,250));
		// Makes a titled border for each scroll frame
		TitledBorder title = BorderFactory.createTitledBorder(players.get(ChessGraphicalView.PLAYER_1).getName());
		title.setTitleJustification(TitledBorder.CENTER);
		playerOneScroll.setBorder(title);
		title = BorderFactory.createTitledBorder(players.get(ChessGraphicalView.PLAYER_2).getName());
		title.setTitleJustification(TitledBorder.CENTER);
		playerTwoScroll.setBorder(title);
		// Adds scroll frame to the side panel
		sidePanel.add(playerOneScroll, BorderLayout.SOUTH);
		sidePanel.add(playerTwoScroll, BorderLayout.NORTH);
		
		if(showDebugMenu){
			createDebugInterface(sidePanel);
		}else{
			createMoveListPanel(sidePanel);
		}		
		
	}
	/**
	 * This method will fill in the grave yard area of each player on the side panel 
	 * @param area The text are to be filled in
	 * @param player The current player 
	 */
	private void fillInPlayerGraveyard(JTextArea area,int player){
		String s = "";
		List<Piece> piecesList = game.getPlayers().get(player).getKills();
		if(piecesList instanceof ArrayList<?>){
			ArrayList<Piece> pieces = (ArrayList<Piece>)piecesList;
			for(Piece p : pieces){
				s += p.getName() + "\n";
			}
			area.setText(s);
			area.setCaretPosition(area.getText().length());
		}
	}
	/**
	 * This will return the text in the debug console
	 * @return Returns the text in the debug console
	 */
	public String getDebugConsoleText(){
		if(textField != null){
			return textField.getText();
		}
		return "";
	}
	/**
	 * This will set the debug console directly and will replace all text in the console to the
	 * message
	 * @param message The message to be displayed
	 */
	public void setDebugText(String message){
		if(textField != null){
			textField.setText(message);
		}
	}
	/**
	 * This method will switch between the debug and move list windows
	 */
	private void switchSideCenterPanel(){
		if (!debugPanelOpened){
			sidePanel.remove(scrollPane);
			createDebugPanel(sidePanel);
			debugPanelOpened = true;
			debugOption.setText(ChessGraphicalView.MOVE_VIEW);
		}else{
			sidePanel.remove(debugConsole);
			createMoveListPanel(sidePanel);
			debugPanelOpened = false;
			debugOption.setText(ChessGraphicalView.DEBUG_VIEW);
		}
		sidePanel.updateUI();
	}
	/**
	 * This will update the players turn for chess game
	 * @param currentPlayer The current player at the moment
	 */
	private void updateCurrentPlayerTurnForChess(Player currentPlayer){
		clock.switchPlayer(currentPlayer);
		
		int index =  game.getPlayers().indexOf(currentPlayer);
		if(index ==ChessGraphicalView.PLAYER_1){
			playerOneScroll.setBackground(ChessGraphicalView.CURRENT_PLAYER_SELECTION_COLOR);
			playerTwoScroll.setBackground(ChessGraphicalView.DEFAULT_PLAYER_SELECTION_COLOR);
		}else if(index == ChessGraphicalView.PLAYER_2){
			playerTwoScroll.setBackground(ChessGraphicalView.CURRENT_PLAYER_SELECTION_COLOR);
			playerOneScroll.setBackground(ChessGraphicalView.DEFAULT_PLAYER_SELECTION_COLOR);
		}
		
		this.displayBoard();
	}

	/**
	 * This method when called will close the view
	 */
	public void closeView() {
		super.closeView();
		this.clock.closeView();
	}
	
	/**
	 * This will print a message on a new line in the debug console
	 * @param message The message to be displayed on the console
	 */
	public void printlnToDebugConsole(String message) {
		if(textField != null){
			printToDebugConsole("\n"+ message);
		}
	}

	/**
	 * This method will print a message to the debug console
	 * @param message The message to be displayed on the console
	 */
	public void printToDebugConsole(String message) {
		if(textField != null){
			textField.append(message);
			if(textField.getText().length() > ChessGraphicalView.MAX_DEBUG_CONSOLE_LENGTH){
				this.clearDebugConsole();
			}
			textField.setCaretPosition(textField.getText().length());
			
		}
	}
	/**
	 * This will update the player highlighting when the current player changes
	 * @param currentPlayer The current player at the moment
	 */
	public void updateCurrentPlayerTurn(Player currentPlayer) {
		updateCurrentPlayerTurnForChess(currentPlayer);	
	}
}
